package cn.t.handler;

import cn.dev33.satoken.exception.NotLoginException;
import cn.t.core.exception.BizException;
import cn.t.core.mode.Result;
import cn.t.core.enums.base.CommonError;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.validation.ValidationException;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

import static cn.t.core.enums.BaseErrorCause.TOKEN_ERROR;


/**
 * @author l
 */
@Slf4j
@RestControllerAdvice
@Order(-9999)
public class RSCAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private MessageSource messageSource;

    /**
     * 请求参数校验失败
     */
    @ExceptionHandler({ValidationException.class})
    public Result<Object> validExceptionHandler(ValidationException e) {
        log.error("请求参数校验失败:{}", e.getMessage(), e);
        return Result.fail(CommonError.ILLEGAL_PARAMETER.getCode(), messageSource.getMessage(CommonError.ILLEGAL_PARAMETER.getCode().toString(), null, Locale.US));
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Object> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        String errorMsg = String.join(",", fieldErrors.stream().map(item -> item.getField() + item.getDefaultMessage()).collect(Collectors.toList()));
        return Result.serverError(errorMsg);
    }

    /**
     * 上传文件未传文件异常
     */
    @ExceptionHandler(MultipartException.class)
    public Result<Object> multipartExceptionHandler(MultipartException e) {
        log.error("请求参数校验失败:{}", e.getMessage(), e);
        return Result.fail(CommonError.ILLEGAL_PARAMETER.getCode(), e.getMessage());
    }

    /**
     * 不支持的请求方法
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result<Object> methodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e) {
        log.error("不支持的请求方法:{}", e.getMessage(), e);
        return Result.fail(CommonError.ILLEGAL_PARAMETER.getCode(), e.getMessage());
    }

    /**
     * 缺失请求参数
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result<Object> methodNotSupportedExceptionHandler(MissingServletRequestParameterException e) {
        log.error("缺失请求参数:{}", e.getMessage(), e);
        return Result.fail(CommonError.ILLEGAL_PARAMETER.getCode(), e.getMessage());
    }


    /**
     * 业务异常
     */
    @ExceptionHandler({BizException.class})
    public Result<Object> handleMyException(BizException ex) {
        log.error("请求参数校验失败:{}", ex.getMessage(), ex);
        if (ex.getCode() != null) {
            return Result.fail(ex.getCode(), ex.getMessage());
        }
        return Result.serverError("业务异常");
    }

//    /**
//     * 运行时异常
//     */
//    @ExceptionHandler({RuntimeException.class})
//    public Result<Object> handleMyException(RuntimeException ex) {
//        log.error("业务异常:{}", ex.getMessage(), ex);
//        return Result.serverError("业务异常");
//    }


    @ExceptionHandler({NotLoginException.class})
    public Result<Object> handleMyException(NotLoginException ex) {
        log.error("登录异常:{}", ex.getMessage());
        return Result.fail(TOKEN_ERROR, ex.getMessage());
    }

//    /**
//     * 未知异常
//     */
//    @ExceptionHandler({Exception.class})
//    public Result<Object> handleMyException(Exception ex) {
//        log.error("业务异常:{}", ex.getMessage(), ex);
//        return Result.serverError("业务异常");
//    }

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof String || body instanceof Result ) {
            return body;
        }

        if (returnType.getParameterType().getSimpleName().equals("void")) {
            return Result.success(Boolean.TRUE);
        }

        return Result.success(body);
    }


}
